package com.example.demojava.service.impl;

import com.example.demojava.entity.FileInfo;
import com.example.demojava.repository.FileInfoRepository;
import com.example.demojava.service.FileService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

@Service
public class FileServiceImpl implements FileService {

    @Value("${file.upload.path}")
    private String uploadPath;

    @Autowired
    private FileInfoRepository fileInfoRepository;

    @Override
    @Transactional
    public FileInfo initUpload(String fileName, String fileHash, Long totalSize) {
        FileInfo fileInfo = fileInfoRepository.findByFileHash(fileHash);
        if (fileInfo != null) {
            return fileInfo;
        }

        fileInfo = new FileInfo();
        fileInfo.setName(fileName);
        fileInfo.setFileHash(fileHash);
        fileInfo.setTotalSize(totalSize);
        fileInfo.setUploadedSize(0L);
        fileInfo.setStatus(0);
        fileInfo.setSavePath(uploadPath); // 只保存基础路径

        // 创建临时目录
        try {
            Files.createDirectories(Paths.get(uploadPath + fileHash));
        } catch (IOException e) {
            throw new RuntimeException("创建上传目录失败", e);
        }

        return fileInfoRepository.save(fileInfo);
    }

    @Override
    @Transactional
    public FileInfo uploadChunk(String fileHash, Long chunkNumber, MultipartFile chunk) {
        FileInfo fileInfo = fileInfoRepository.findByFileHash(fileHash);
        if (fileInfo == null) {
            throw new RuntimeException("文件上传未初始化");
        }

        String chunkPath = uploadPath + fileHash + "/" + chunkNumber;
        try {
            chunk.transferTo(new File(chunkPath));
            fileInfo.setUploadedSize(fileInfo.getUploadedSize() + chunk.getSize());
            return fileInfoRepository.save(fileInfo);
        } catch (IOException e) {
            throw new RuntimeException("分片上传失败", e);
        }
    }

    @Override
    public FileInfo getUploadProgress(String fileHash) {
        return fileInfoRepository.findByFileHash(fileHash);
    }

    @Override
    @Transactional
    public void completeUpload(String fileHash) {
        FileInfo fileInfo = fileInfoRepository.findByFileHash(fileHash);
        if (fileInfo == null) {
            throw new RuntimeException("文件不存在");
        }

        // 检查文件是否已经完成上传
        if (fileInfo.getStatus() == 1) {
            return; // 如果已经完成上传，直接返回
        }

        // 合并文件
        try {
            Path targetPath = Paths.get(uploadPath + fileInfo.getName());

            // 如果目标文件已存在，先删除
            if (Files.exists(targetPath)) {
                Files.delete(targetPath);
            }

            Files.createFile(targetPath);

            // 合并所有分片
            File chunkDir = new File(uploadPath + fileHash);
            File[] chunks = chunkDir.listFiles();
            if (chunks != null) {
                for (File chunk : chunks) {
                    Files.write(targetPath, Files.readAllBytes(chunk.toPath()),
                            java.nio.file.StandardOpenOption.APPEND);
                }
            }

            // 更新文件状态
            fileInfo.setStatus(1);
            fileInfoRepository.save(fileInfo);

            // 删除临时目录
            deleteDirectory(chunkDir);
        } catch (IOException e) {
            throw new RuntimeException("文件合并失败", e);
        }
    }

    private void deleteDirectory(File directory) {
        File[] files = directory.listFiles();
        if (files != null) {
            for (File file : files) {
                if (file.isDirectory()) {
                    deleteDirectory(file);
                }
                file.delete();
            }
        }
        directory.delete();
    }
}